package com.zkadmin.renderer;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.DefaultTreeNode;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Window;

import com.zkadmin.constraints.ZulPageConstraint;
import com.zkadmin.controller.MenuListCtrl;
import com.zkadmin.entity.SysMenu;
import com.zkadmin.service.SysMenuService;
import com.zkadmin.util.AdminConstants;
import com.zkadmin.util.AdminWebUtils;
import com.zkadmin.util.MsgBox;

public class SysMenuListTreeitemRenderer extends BaseRenderer implements TreeitemRenderer<DefaultTreeNode<SysMenu>> {
	private SysMenuService sysMenuService;
	private MenuListCtrl menuListCtrl;
	private Window win;

	public SysMenuListTreeitemRenderer(Window win, MenuListCtrl menuListCtrl, SysMenuService sysMenuService) {
		this.sysMenuService = sysMenuService;
		this.menuListCtrl = menuListCtrl;
		this.win = win;
	}

	@Override
	public void render(final Treeitem treeitem, DefaultTreeNode<SysMenu> data, int index) throws Exception {
		final SysMenu menu = data.getData();
		Treerow treerow = new Treerow();
		treeitem.setOpen(true);
		treeitem.appendChild(treerow);

		if (SecurityUtils.getSubject().hasRole(AdminConstants.ROLE_ADMIN) || SecurityUtils.getSubject().isPermitted("sys:menu:update")) {
			final Textbox nameBox = new Textbox(menu.getName());
			nameBox.setInplace(true);
			nameBox.setWidth("60%");
			createTreecell(treerow).appendChild(nameBox);
			nameBox.addEventListener(Events.ON_CHANGE, new EventListener<Event>() {
				@Override
				public void onEvent(Event event) throws Exception {
					menu.setName(nameBox.getValue());
					saveAndRefresh(menu);
				}

			});

			createTreecell(treerow).setLabel(menu.getCode());

			final Textbox urlBox = new Textbox(menu.getUrl());
			urlBox.setInplace(true);
			urlBox.setWidth("80%");
			createTreecell(treerow).appendChild(urlBox);
			urlBox.addEventListener(Events.ON_CHANGE, new EventListener<Event>() {
				@Override
				public void onEvent(Event event) throws Exception {
					menu.setUrl(urlBox.getValue());
					saveAndRefresh(menu);
				}

			});
			urlBox.setConstraint(new ZulPageConstraint());

			final Textbox iconBox = new Textbox(menu.getIcon());
			iconBox.setInplace(true);
			iconBox.setWidth("80%");
			createTreecell(treerow).appendChild(iconBox);
			iconBox.addEventListener(Events.ON_CHANGE, new EventListener<Event>() {
				@Override
				public void onEvent(Event event) throws Exception {
					menu.setIcon(iconBox.getValue());
					saveAndRefresh(menu);
				}

			});

			final Checkbox isOpenCheckBox = new Checkbox();
			isOpenCheckBox.setChecked(menu.isOpen());
			Treecell isOpenCell = createTreecell(treerow);
			isOpenCell.setStyle("text-align:center");
			isOpenCell.appendChild(isOpenCheckBox);
			isOpenCheckBox.addEventListener(Events.ON_CHECK, new EventListener<Event>() {
				@Override
				public void onEvent(Event event) throws Exception {
					menu.setOpen(isOpenCheckBox.isChecked());
					saveAndRefresh(menu);
				}

			});

			final Intbox sortBox = new Intbox(menu.getSort());
			sortBox.setInplace(true);
			sortBox.setWidth("90%");
			sortBox.setParent(createTreecell(treerow));
			sortBox.addEventListener(Events.ON_CHANGE, new EventListener<Event>() {
				@Override
				public void onEvent(Event event) throws Exception {
					menu.setSort(sortBox.getValue());
					saveAndRefresh(menu);
				}
			});
		} else {
			createTreecell(treerow).setLabel(menu.getName());
			createTreecell(treerow).setLabel(menu.getCode());
			createTreecell(treerow).setLabel(menu.getUrl());
			createTreecell(treerow).setLabel(menu.getIcon());
			createTreecell(treerow).setLabel(menu.isOpen() ? "展开" : "关闭");
			createTreecell(treerow).setLabel(menu.getSort() + "");
		}

		Hbox hbox = createHbox(treerow);
		final Button newBtn = new Button("新建");
		if (!SecurityUtils.getSubject().hasRole(AdminConstants.ROLE_ADMIN)) {
			newBtn.setDisabled(!SecurityUtils.getSubject().isPermitted("sys:menu:create"));
		}
		newBtn.setIconSclass("z-icon-plus");
		hbox.appendChild(newBtn);
		newBtn.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
			@Override
			public void onEvent(Event event) throws Exception {
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("menu", menu);
				Window window = (Window) Executions.createComponents(AdminWebUtils.getZulPagePath("admin/create_menu_dialog.zul"), win, args);
				window.addEventListener(AdminConstants.EVENT_ONREFRESH, new EventListener<Event>() {
					@Override
					public void onEvent(Event event) throws Exception {
						menuListCtrl.refreshData();
					}
				});
				AdminWebUtils.addCaption(window, newBtn.getIconSclass());
				window.doModal();
			}
		});

		Button delBtn = new Button("删除");
		if (!SecurityUtils.getSubject().hasRole(AdminConstants.ROLE_ADMIN)) {
			delBtn.setDisabled(!SecurityUtils.getSubject().isPermitted("sys:menu:delete"));
		}
		delBtn.setIconSclass("z-icon-times");
		hbox.appendChild(delBtn);
		delBtn.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
			@Override
			public void onEvent(Event event) throws Exception {
				Messagebox.show("删除此菜单其子菜单也将删除，是否继续删除？", "删除确认", Messagebox.YES | Messagebox.NO, Messagebox.QUESTION, new EventListener<Event>() {
					@Override
					public void onEvent(Event event) throws Exception {
						if (Messagebox.ON_YES.equals(event.getName())) {
							List<SysMenu> subMenus = sysMenuService.findByCodeLike(menu.getCode() + "%");
							for (SysMenu subMenu : subMenus) {
								subMenu.getRoles().clear();
								sysMenuService.delete(subMenu.getId());
							}
							menuListCtrl.refreshData();
						}

					}
				});
			}
		});
	}

	private void saveAndRefresh(SysMenu menu) {
		try {
			sysMenuService.save(menu);
		} catch (ObjectOptimisticLockingFailureException e) {
			MsgBox.alert(AdminConstants.getErrorDataVersionMessage());
		} finally {
			menuListCtrl.refreshData();
		}
	}
}
